import java.lang.*;
import java.util.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.net.*;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.Cipher;
import java.util.Date;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import sun.misc.BASE64Encoder;
import javax.swing.JOptionPane;


/**
 *This program is a server-client chat that has extra functionalities that encrypt and decrypt the messages 
 *created by Tousif Khan <tousifkhan510@gmail.com>
 *@link visit www.techzoo.org 
 *
 *
 *@author Piros, Kevin
 *@author Bautista, Joshua Ivesten 
 *@author Bueno, Benedict Lorenzo
 *@author Butche, Raphael Brian
 *
 *
 *@return Nothing
 *
 **/
public class Chat extends JFrame  implements Runnable {


		public final static int NULL = 0;
	   	public final static int DISCONNECTED = 1;
	  	public final static int DISCONNECTING = 2;
	   	public final static int BEGIN_CONNECT = 3;
	   	public final static int CONNECTED = 4;

	   /**
	    *Prompts the status message if connected or disconnected
	    **/
	   public final static String statusMessages[] = {
	      " Error! Could not connect!", " Disconnected",
	      " Disconnecting...", " Connecting...", " Connected"
	   };
	   
	   /**
	    *Instantiates a new Chat method
	    **/
	   public final static Chat chat = new Chat();
	   public static SimpleDateFormat sdfDate = new SimpleDateFormat("MM-DD-YYYY HH:mm:ss" );
	   public static Date now = new Date();
	   public static String strDate = sdfDate.format(now);
	   public final static String END_CHAT_SESSION = new Character((char)0).toString(); // Indicates the end of a session
	   
	   /**
	    *States the connection information
	    **/
	   public static String hostIP = "localhost";
	   public static int port = 5000;
	   public static int connectionStatus = DISCONNECTED;
	   public static boolean isHost = true;
	   public static String statusString = statusMessages[connectionStatus];
	   public String s;
	   public static StringBuffer toAppend = new StringBuffer("");
	   public static StringBuffer toSend = new StringBuffer("");
	   public String message = "";

		/**
		 *Resources for the UI method
		 **/
		private final static boolean shouldFill = true;
		private final static boolean shouldWeightX = true;
		private JFrame messageFrame,DescryptFrame,AskFrame,welcomeFrame;
		private static JPanel mainPanel,messagePanel,DescryptPanel,AskPanel,welcomePanel;
		private static JPanel mainBGPanel,messageBGPanel,DescryptBGPanel,AskBGPanel,welcomeBGPanel;
		private Dimension mainFrameSize,messageFramesize,DescryptFramesize,AskFramesize,welcomeFramesize;
		private JTextField UserText,HostIP,Port,messageText;
		public static JTextField Code,welcomename;
		private ButtonHandler bh = new ButtonHandler();
		private JButton Login,Quit,Connect,Disconnect,descrypt,logout,send,okay,Yes,No,welcomeokay;
		private static JTextArea messages,User;
		private static JPanel messageTextPanel,messagesPanel,ButtonPanel,All,messageTextPanel2,messagesPanel2,ButtonPanel2;
		public static JRadioButton hostOption,guestOption;
		public static JPanel statusBar = null;
  		public static JLabel statusField = null;
   		public static JTextField statusColor = null;
		
		public static ServerSocket hostServer = null;
	   	public static Socket socket = null;
	   	public static BufferedReader in = null;
	   	public static PrintWriter out = null;

		/**
		*Constructor method for chat
		**/
		public Chat(){
			super();
		 	setUndecorated(true);
	        setBackground(new Color(0,0,0,0));
	        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	        pack();


	        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
			int x = ((int)screenSize.getWidth()/2)-250;
			int y = ((int)screenSize.getHeight()/2)-290;
			setLocation(x,y);
				GridBagConstraints superCon = new GridBagConstraints();

				
			/**
			 *Main Frame for UI
			 **/
			ImageIcon mainBG = new ImageIcon("images/main.png");
        	Dimension mainBGSize = new Dimension(mainBG.getIconWidth(), mainBG.getIconHeight());
        	setSize(mainBGSize);


			mainBGPanel = new JPanel() {
				public void paintComponent(Graphics g) {
						Image img = new ImageIcon("images/main.png").getImage();
						Dimension size = new Dimension(img.getWidth(null), img.getHeight(null));
						setPreferredSize(size);
						setMinimumSize(size);
						setMaximumSize(size);
						setSize(size);
						setLayout(null);
						g.drawImage(img, 0, 0, null);
					}
				};
			mainBGPanel.setBounds(0, 0, mainBG.getIconWidth(), mainBG.getIconHeight());

				mainPanel = new JPanel(new GridBagLayout());
				mainPanel.setOpaque(false);
				GridBagConstraints mainCon = new GridBagConstraints();
				mainPanel.setOpaque(false);
				mainPanel.setSize(mainBGSize);

				if(shouldFill){
					mainCon.fill = GridBagConstraints.HORIZONTAL;


				}
				Font font1 = new Font("SansSerif", Font.BOLD, 15);
				Font font2 = new Font("Courier New", Font.BOLD,20);

				 ActionAdapter buttonListener = null;
				 buttonListener = new ActionAdapter() {
                 public void actionPerformed(ActionEvent e) {
               if (connectionStatus != DISCONNECTED) {
                  changeStatusNTS(NULL, true);
               }
               else {
                  isHost = e.getActionCommand().equals("host");

                  /**
                   *Cannot supply host IP if host option is chosen
                   **/
                  if (isHost) {
                     HostIP.setEnabled(false);
                     HostIP.setText("localhost");
                     hostIP = "localhost";
                  }
                  else {
                    HostIP.setEnabled(true);
                  }
               }
            }
         };
         
         	/**
         	*User Frame, Chooses if the user is the host or the client
         	**/
			ButtonGroup bg = new ButtonGroup();
		    hostOption = new JRadioButton("Host", true);
		    hostOption.setOpaque(false);
		    hostOption.setFont(font1);
		    hostOption.setMnemonic(KeyEvent.VK_H);
		    hostOption.setActionCommand("host");
		    hostOption.addActionListener(buttonListener);
		    mainCon.gridx=0;
		    mainCon.gridy=0;
		    mainCon.insets = new Insets(180,80,0,-40);
		    mainPanel.add(hostOption,mainCon);

		    guestOption = new JRadioButton("Guest", false);
		    guestOption.setOpaque(false);
		    guestOption.setFont(font1);
		    guestOption.setMnemonic(KeyEvent.VK_G);
		    guestOption.setActionCommand("guest");
      		guestOption.addActionListener(buttonListener);
		    mainCon.gridx=1;
		    mainCon.gridy=0;
		    mainPanel.add(guestOption,mainCon);
 			bg.add(hostOption);
      		bg.add(guestOption);

			Login = new ImageButton("images/log.png");
			Login.setOpaque(false);
			Login.setActionCommand("login");
			Login.addActionListener(bh);
			Login.setBorder(null);
			Login.setContentAreaFilled(false);
			mainCon.gridx=0;
     		mainCon.gridy=1;
     		mainCon.insets = new Insets(70,20,0,20);
			mainPanel.add(Login,mainCon);

			Quit = new ImageButton("images/quit.png");
			Quit.setOpaque(false);
			Quit.setActionCommand("quit");
			Quit.addActionListener(bh);
			Quit.setBorder(null);
			Quit.setContentAreaFilled(false);
			mainCon.gridx=1;
     		mainCon.gridy=1;
			mainPanel.add(Quit,mainCon);

			mainBGPanel.add(mainPanel);
			setContentPane(mainBGPanel);

			/**
			*Message Frame for the UI
			**/
			messageFrame = new JFrame("USER");
			messageFrame.setLayout(new GridBagLayout());
	        messageFrame.setUndecorated(true);
	        messageFrame.setBackground(new Color(0,0,0,0));
	        messageFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	        messageFrame.setLocation(x-240,y);
	        
	        ImageIcon messageBG = new ImageIcon("images/ChatFrame.png");
        	Dimension messageBGSize = new Dimension(messageBG.getIconWidth(), messageBG.getIconHeight());
        	messageFrame.setSize(messageBGSize);

	        messageBGPanel = new JPanel() {
				public void paintComponent(Graphics g) {
						Image img = new ImageIcon("images/ChatFrame.png").getImage();
						Dimension size = new Dimension(img.getWidth(null), img.getHeight(null));
						setPreferredSize(size);
						setMinimumSize(size);
						setMaximumSize(size);
						setSize(size);
						setLayout(null);
						g.drawImage(img, 0, 0, null);
					}
				};
			messageBGPanel.setBounds(0, 0, messageBG.getIconWidth(),messageBG.getIconHeight());

			messagePanel = new JPanel(new GridBagLayout());
			GridBagConstraints messageCon = new GridBagConstraints();
			messagePanel.setOpaque(false);
			messagePanel.setSize(messageBGSize);

			messagesPanel2 = new JPanel ();
			messagesPanel2.setOpaque(false);
			GridBagConstraints messagesArea2 = new GridBagConstraints();

			messagesPanel = new JPanel ();
			messagesPanel.setOpaque(false);
			GridBagConstraints messagesArea = new GridBagConstraints();
			messages =new JTextArea(7,40);
			messages.setEditable(false);
			messages.setBackground(new Color(60,60,158));
			JScrollPane scroll= new JScrollPane(messages,
           	JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
           	JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
			messagesPanel.add(scroll,messagesArea);
			messagesPanel2.add(messagesPanel,messagesArea2);


			messageTextPanel2 = new JPanel ();
			messageTextPanel2.setOpaque(false);
			GridBagConstraints messageTextArea2 = new GridBagConstraints();
			
			messageTextPanel = new JPanel ();
			messageTextPanel.setOpaque(false);
			GridBagConstraints messageTextArea = new GridBagConstraints();
			messageText = new JTextField(20);
      		messageText.addActionListener(new ActionAdapter() {
      			
      		/**
      		 *action listener for message text,the message text stores the time of which the message was sent
      		 *and sends to string to the client 
      		 **/
            public void actionPerformed(ActionEvent e) {
            	s = messageText.getText();
               if (!s.equals("")) {
                  appendToChatBox( strDate +" ]]------------->" + s + "\n");
                  messageText.selectAll();
                  // Send the string
                  sendString(s);
                  System.out.print(s);
               }
            }
         });
			messageTextPanel.add(messageText,messageTextArea);


			send = new ImageButton("images/send.png");
			send.setOpaque(false);
			send.addActionListener(bh);
			send.setActionCommand("send");
			send.setBorder(null);
			send.setContentAreaFilled(false);
			messageTextPanel.add(send,messageTextArea);
			messageTextPanel2.add(messageTextPanel,messageTextArea2);

			ButtonPanel2 = new JPanel ();
			ButtonPanel2.setOpaque(false);
			GridBagConstraints ButtonArea2 = new GridBagConstraints();

			ButtonPanel = new JPanel ();
			ButtonPanel.setOpaque(false);
			GridBagConstraints ButtonArea = new GridBagConstraints();
			
			/**
			*Frame for the decrypt UI
			**/
			descrypt = new ImageButton("images/descrypt.png");
			descrypt.setOpaque(false);
			descrypt.setActionCommand("descrypt");
			descrypt.addActionListener(bh);
			descrypt.setBorder(null);
			descrypt.setContentAreaFilled(false);
			ButtonPanel.add(descrypt,ButtonArea);

			logout = new ImageButton("images/logout.png");
			logout.setOpaque(false);
			logout.setActionCommand("logout");
			logout.addActionListener(bh);
			logout.setBorder(null);
			logout.setContentAreaFilled(false);
			ButtonPanel.add(logout,ButtonArea);
			ButtonPanel2.add(ButtonPanel,ButtonArea2);


			statusField = new JLabel();
      		statusField.setText(statusMessages[DISCONNECTED]);
   			statusColor = new JTextField(6);
      		statusColor.setBackground(Color.red);
      		statusColor.setEditable(false);
    		statusBar = new JPanel(new BorderLayout());
    		statusBar.setOpaque(false);
      		statusBar.add(statusColor, BorderLayout.WEST);
      		statusBar.add(statusField, BorderLayout.CENTER);


			UserText = new JTextField(20);
			UserText.setFont(font1);
			UserText.setForeground(Color.WHITE);
			UserText.setBackground(new Color(60,60,158));
			UserText.setBorder(javax.swing.BorderFactory.createEmptyBorder());

   	 		HostIP = new JTextField(20);
   	 		HostIP.setFont(font1);
   	 		HostIP.setForeground(Color.WHITE);
     		HostIP.setText(hostIP);
     		HostIP.setEnabled(false);
     		HostIP.addFocusListener(new FocusAdapter() {

            public void focusLost(FocusEvent e) {
              HostIP.selectAll();
               if (connectionStatus != DISCONNECTED) {
                  changeStatusNTS(NULL, true);
               }
               else {
                  hostIP = HostIP.getText();
               }
            }
         });
   	 		HostIP.setBackground(new Color(60,60,158));
   	 		HostIP.setBorder(javax.swing.BorderFactory.createEmptyBorder());


   	 		Port = new JTextField(20);
   	 		Port.setEditable(true);
   	 		Port.setFont(font1);
   	 		Port.setForeground(Color.WHITE);
      		Port.setText((new Integer(port)).toString());
      		Port.addFocusListener(new FocusAdapter() {
      		/**
      		*Connection status if the user is connected or disconnected
      		*the connection status can only be edited when disconnected
      		*@exception NumberFormatException on input error
      		**/
            public void focusLost(FocusEvent e) {
               if (connectionStatus != DISCONNECTED) {
                  changeStatusNTS(NULL, true);
               }
               else {
                  int temp;
                  try {
                     temp = Integer.parseInt(Port.getText());
                     port = temp;
                  }
                  catch (NumberFormatException nfe) {
                     Port.setText((new Integer(port)).toString());
                     mainPanel.repaint();
                  }
               }
            }
         });
   	 		Port.setBackground(new Color(60,60,158));
   	 		Port.setBorder(javax.swing.BorderFactory.createEmptyBorder());


   	 		Connect = new ImageButton("images/connect.png");
   	 		buttonListener = new ActionAdapter() {
            public void actionPerformed(ActionEvent e) {
               /**
                *Requests a connection initiation
                *
                **/
               if (e.getActionCommand().equals("connect")) {
                    changeStatusNTS(BEGIN_CONNECT, true);
					welcomename.setText(UserText.getText());
                  	messageFrame.setVisible(true);
	    			Connect.setVisible(false);
	    			Disconnect.setVisible(true);
					Disconnect.setEnabled(true);
					 welcomeFrame.setVisible(true);
               }
               /**
                *if not disconnect
                **/ 
               else {
                  changeStatusNTS(DISCONNECTING, true);
               }
            }
         };
         	/**
         	 *Functionalities of each button in the User Interface
         	 **/
			Connect.setOpaque(false);
			Connect.setMnemonic(KeyEvent.VK_C);
      		Connect.setActionCommand("connect");
      		Connect.addActionListener(buttonListener);
      		Connect.setEnabled(true);
			Connect.setActionCommand("connect");
			Connect.addActionListener(bh);
			Connect.setBorder(null);
			Connect.setContentAreaFilled(false);


			Disconnect = new ImageButton("images/disconnect.png");
			Disconnect.setOpaque(false);
			Disconnect.setMnemonic(KeyEvent.VK_D);
      		Disconnect.setActionCommand("disconnect");
      		Disconnect.addActionListener(buttonListener);
      		Disconnect.setEnabled(false);
			Disconnect.setActionCommand("disconnect");
			Disconnect.addActionListener(bh);
			Disconnect.setBorder(null);
			Disconnect.setContentAreaFilled(false);
			Disconnect.setVisible(false);

				messageCon.gridx=0;
   	 		messageCon.gridy=0;
   	 		messageCon.ipady=5;
   	 		messageCon.insets = new Insets(30,340,0,0);
			messagePanel.add( statusBar,messageCon);

			messageCon.gridx=1;
   	 		messageCon.gridy=0;
			messageCon.insets = new Insets(20,-100,0,0);
			messagePanel.add(Connect,messageCon);

			messageCon.gridx=1;
   	 		messageCon.gridy=0;
			messageCon.insets = new Insets(20,-100,0,0);
			messagePanel.add(Disconnect,messageCon);

   	 		messageCon.ipady=5;
   	 		messageCon.gridx=0;
   	 		messageCon.gridy=1;
   	 		messageCon.insets = new Insets(6,440,0,0);
   	 		messagePanel.add(UserText,messageCon);

   	 		messageCon.ipady=5;
   	 		messageCon.gridx=0;
   	 		messageCon.gridy=2;
   	 		messageCon.insets = new Insets(6,440,0,0);
   	 		messagePanel.add(HostIP,messageCon);

   	 		messageCon.ipady=5;
   	 		messageCon.gridx=0;
   	 		messageCon.gridy=3;
   	 		messageCon.insets = new Insets(6,440,0,0);
   	 		messagePanel.add(Port,messageCon);

   	 		messageCon.gridx=0;
   	 		messageCon.gridy=4;
   	 		messageCon.insets = new Insets(5,285,0,0);
			messagePanel.add(ButtonPanel2,messageCon);

			messageCon.gridx=0;
   	 		messageCon.gridy=5;
   	 		messageCon.insets = new Insets(10,265,0,0);
   	 		messageCon.gridwidth=2;
			messagePanel.add(messagesPanel2,messageCon);
			messageCon.gridx=0;
   	 		messageCon.gridy=6;
   	 		messageCon.insets = new Insets(-20,250,0,0);
			messagePanel.add(messageTextPanel2,messageCon);

			messageBGPanel.add(messagePanel);
			messageFrame.add(messageBGPanel);

			DescryptFrame = new JFrame("USER");
			DescryptFrame.setLayout(new GridBagLayout());
	       	DescryptFrame.setUndecorated(true);
	        DescryptFrame.setBackground(new Color(0,0,0,0));
	        DescryptFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	        DescryptFrame.setLocation(x,y+230);

	        ImageIcon DescryptBG = new ImageIcon("images/code.png");
        	Dimension DescryptBGSize = new Dimension(DescryptBG.getIconWidth(), DescryptBG.getIconHeight());
        	DescryptFrame.setSize(DescryptBGSize);
			/**
			 *Decrypt Panel for the decrpyt UI 
			 **/
	        DescryptBGPanel = new JPanel() {
				public void paintComponent(Graphics g) {
						Image img = new ImageIcon("images/code.png").getImage();
						Dimension size = new Dimension(img.getWidth(null), img.getHeight(null));
						setPreferredSize(size);
						setMinimumSize(size);
						setMaximumSize(size);
						setSize(size);
						setLayout(null);
						g.drawImage(img, 0, 0, null);
					}
				};
			DescryptBGPanel.setBounds(0, 0, DescryptBG.getIconWidth()+20,DescryptBG.getIconHeight()+40);
			
			
			/**
			 *Decrypt panel for the decrypt UI
			 **/
			DescryptPanel = new JPanel(new GridBagLayout());
			GridBagConstraints DescryptCon = new GridBagConstraints();
			DescryptPanel.setOpaque(false);
			DescryptPanel.setSize(messageBGSize);

			Code = new JTextField(25);
			Code.setOpaque(false);
   	 		Code.setBorder(javax.swing.BorderFactory.createEmptyBorder());
	   		Code.setFont(font1);
	   	 	DescryptCon.ipady=38;
	   	 	DescryptCon.gridx=0;
   	 		DescryptCon.gridy=0;
   	 		DescryptCon.insets = new Insets(30,320,0,0);
   	 		DescryptPanel.add(Code,DescryptCon);

   	 	   	okay = new ImageButton("images/okay.png");
			okay.setOpaque(false);
			okay.setActionCommand("okay");
			okay.addActionListener(bh);
			okay.setBorder(null);
			okay.setContentAreaFilled(false);
			DescryptCon.gridx=0;
   	 		DescryptCon.gridy=1;
   	 		DescryptCon.insets = new Insets(50,170,0,0);
   	 		DescryptPanel.add(okay,DescryptCon);


			DescryptBGPanel.add(DescryptPanel);
			DescryptFrame.add(DescryptBGPanel);

			/**
			*Asks the user if he/she wants to quit
			**/
			AskFrame = new JFrame("USER");
			AskFrame.setLayout(new GridBagLayout());
	       	AskFrame.setUndecorated(true);
	        AskFrame.setBackground(new Color(0,0,0,0));
	        AskFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	        AskFrame.setLocation(x+50,y+100);

	        ImageIcon AskBG = new ImageIcon("images/AskFrame.png");
        	Dimension AskBGSize = new Dimension(AskBG.getIconWidth(), AskBG.getIconHeight());
        	AskFrame.setSize(AskBGSize);

	        AskBGPanel = new JPanel() {
				public void paintComponent(Graphics g) {
						Image img = new ImageIcon("images/AskFrame.png").getImage();
						Dimension size = new Dimension(img.getWidth(null), img.getHeight(null));
						setPreferredSize(size);
						setMinimumSize(size);
						setMaximumSize(size);
						setSize(size);
						setLayout(null);
						g.drawImage(img, 0, 0, null);
					}
				};
			AskBGPanel.setBounds(0, 0, AskBG.getIconWidth()+20,AskBG.getIconHeight()+40);

			AskPanel = new JPanel(new GridBagLayout());
			GridBagConstraints AskCon = new GridBagConstraints();
			AskPanel.setOpaque(false);
			AskPanel.setSize(AskBGSize);

			Yes = new ImageButton("images/Yes.png");
			Yes.setOpaque(false);
			Yes.setActionCommand("Yes");
			Yes.addActionListener(bh);
			Yes.setBorder(null);
			Yes.setContentAreaFilled(false);
			AskCon.gridx=0;
     		AskCon.gridy=1;
     		AskCon.insets = new Insets(110,30,0,0);
			AskPanel.add(Yes,AskCon);

			No = new ImageButton("images/No.png");
			No.setOpaque(false);
			No.setActionCommand("No");
			No.addActionListener(bh);
			No.setBorder(null);
			No.setContentAreaFilled(false);
			AskCon.gridx=1;
     		AskCon.gridy=1;
			AskPanel.add(No,AskCon);

			AskBGPanel.add(AskPanel);
			AskFrame.add(AskBGPanel);
			
			welcomeFrame = new JFrame("USER");
			welcomeFrame.setLayout(new GridBagLayout());
	       	welcomeFrame.setUndecorated(true);
	        welcomeFrame.setBackground(new Color(0,0,0,0));
	        welcomeFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	        welcomeFrame.setLocation(x,y+230);

	        ImageIcon welcomeBG = new ImageIcon("images/welcome.png");
        	Dimension welcomeBGSize = new Dimension(welcomeBG.getIconWidth(), welcomeBG.getIconHeight());
        	welcomeFrame.setSize(welcomeBGSize);

	        welcomeBGPanel = new JPanel() {
				public void paintComponent(Graphics g) {
						Image img = new ImageIcon("images/welcome.png").getImage();
						Dimension size = new Dimension(img.getWidth(null), img.getHeight(null));
						setPreferredSize(size);
						setMinimumSize(size);
						setMaximumSize(size);
						setSize(size);
						setLayout(null);
						g.drawImage(img, 0, 0, null);
					}
				};
			welcomeBGPanel.setBounds(0, 0, welcomeBG.getIconWidth()+20,welcomeBG.getIconHeight()+40);

			welcomePanel = new JPanel(new GridBagLayout());
			GridBagConstraints welcomeCon = new GridBagConstraints();
			welcomePanel.setOpaque(false);
			welcomePanel.setSize(messageBGSize);

			welcomename = new JTextField(25);
			welcomename.setOpaque(false);
   	 		welcomename.setBorder(javax.swing.BorderFactory.createEmptyBorder());
	   		welcomename.setFont(font2);
	   		welcomename.setForeground(Color.WHITE);
	   		
	   	
	   	 	welcomeCon.ipady=38;
	   	 	welcomeCon.gridx=0;
   	 		welcomeCon.gridy=0;
   	 		welcomeCon.insets = new Insets(30,320,0,0);
   	 		welcomePanel.add(welcomename,welcomeCon);
   	 		

   	 	   	welcomeokay = new ImageButton("images/okay.png");
			welcomeokay.setOpaque(false);
			welcomeokay.setActionCommand("welcomeokay");
			welcomeokay.addActionListener(bh);
			welcomeokay.setBorder(null);
			welcomeokay.setContentAreaFilled(false);
			welcomeCon.gridx=0;
   	 		welcomeCon.gridy=1;
   	 		welcomeCon.insets = new Insets(50,170,0,0);
   	 		welcomePanel.add(welcomeokay,welcomeCon);

   	 	
			welcomeBGPanel.add(welcomePanel);
			welcomeFrame.add(welcomeBGPanel);


}
/**
 *ActionListener for all of the functionalities of the program
 **/
final class ButtonHandler implements ActionListener{
	    		public void actionPerformed (ActionEvent e){
	    				if (e.getActionCommand().equals("login")){
	    					messageFrame.setVisible(true);
	    					mainBGPanel.setVisible(false);
	    				} else if (e.getActionCommand().equals("quit")){
	    					System.exit(0);
	    				}else if(e.getActionCommand().equals("send")){
	    					s = messageText.getText();
               				 if (!s.equals("")) {
                  		      appendToChatBox( strDate +" ]]------------->" + s.toUpperCase() + "\n");
                 			 messageText.selectAll();
                  			// Send the string
                               sendString(s);
            			}
	    				}	else if (e.getActionCommand().equals("disconnect")){
	    					Connect.setVisible(true);
	    					Disconnect.setVisible(false);
	    				} else if (e.getActionCommand().equals("quituser")){
	    					mainBGPanel.setVisible(true);
	    					Connect.setVisible(true);
	    					Disconnect.setVisible(false);
	    					messageFrame.dispose();
	    				} else if (e.getActionCommand().equals("logout")){
	    					AskFrame.setVisible(true);
	    					messageFrame.setVisible(false);
	    				} else if (e.getActionCommand().equals("descrypt")){
	    					DescryptFrame.setVisible(true);
	    					messageFrame.dispose();
	    				} else if (e.getActionCommand().equals("okay")){
	    					DescryptFrame.dispose();
	    					messageFrame.setVisible(true);
	    				} else if (e.getActionCommand().equals("Yes")){
	    					System.exit(0);
	    				} else if (e.getActionCommand().equals("No")){
	    					AskFrame.dispose();
	    					messageFrame.setVisible(true);
	    				} else if (e.getActionCommand().equals("welcomeokay")){
	    				welcomeFrame.setVisible(false);
	    				}
	    		}

}
 private static void changeStatusTS(int newConnectStatus, boolean noError) {
      /** Changes the state if valid state */
      if (newConnectStatus != NULL) {
         connectionStatus = newConnectStatus;
      }

      /** Checks if there is no error, display the appropriate status message */
      if (noError) {
         statusString = statusMessages[connectionStatus];
      }
      /** Otherwise, display error message */
      else {
         statusString = statusMessages[NULL];
      }

      /** Call the run() routine (Runnable interface) on the
        *error-handling and GUI-update thread
      */
   SwingUtilities.invokeLater(chat);
     SwingUtilities.invokeLater(chat);

   }
   
   /**
    *Changes the state if valid state
    *If there are no erros, displays the appropriate status message
    *Otherwise, displays the error message
    */
   private static void changeStatusNTS(int newConnectStatus, boolean noError) {

      if (newConnectStatus != NULL) {
         connectionStatus = newConnectStatus;
      }

      if (noError) {
         statusString = statusMessages[connectionStatus];
      }

      else {
         statusString = statusMessages[NULL];
      }

      /**
       *Call the run() routine (Runnable interface) on the
       *current thread 
      */
      chat.run();
      chat.run();
   }

    private static void appendToChatBox(String s) {
      synchronized (toAppend) {
         toAppend.append(s);
      }
   }

   
   /** Add text to send-buffer */
   private static void sendString(String s) {
      synchronized (toSend) {
         toSend.append(s + "\n");
      }
   }


   /** 
    *Cleanup for disconnect
    *@exception IOException on input
    */
   private static void cleanUp() {
      try {
         if (hostServer != null) {
            hostServer.close();
            hostServer = null;
         }
      }
      catch (IOException e) { hostServer = null; }

      try {
         if (socket != null) {
            socket.close();
            socket = null;
         }
      }
      catch (IOException e) { socket = null; }

      try {
         if (in != null) {
            in.close();
            in = null;
         }
      }
      catch (IOException e) { in = null; }

      if (out != null) {
         out.close();
         out = null;
      }
   }
   
   	  /**
   	   *checks the connection status 
   	   **/
      public void run() {
      switch (connectionStatus) {
      case DISCONNECTED:
         Connect.setEnabled(true);
         Disconnect.setEnabled(false);
         HostIP.setEnabled(true);
         Port.setEnabled(true);
         hostOption.setEnabled(true);
         guestOption.setEnabled(true);
         messageText.setText("");
          messageText.setEnabled(false);
        statusColor.setBackground(Color.red);
         break;

      case DISCONNECTING:
         Connect.setEnabled(false);
         Disconnect.setEnabled(false);
         HostIP.setEnabled(false);
         Port.setEnabled(false);
         hostOption.setEnabled(false);
         guestOption.setEnabled(false);
         messageText.setEnabled(false);
         statusColor.setBackground(Color.orange);
         break;

      case CONNECTED:
         Connect.setEnabled(false);
         Disconnect.setEnabled(true);
         HostIP.setEnabled(false);
         Port.setEnabled(false);
         hostOption.setEnabled(false);
         guestOption.setEnabled(false);
         messageText.setEnabled(true);
         statusColor.setBackground(Color.green);
         break;

      case BEGIN_CONNECT:
         Connect.setEnabled(false);
         Disconnect.setEnabled(false);
         HostIP.setEnabled(false);
         Port.setEnabled(false);
         hostOption.setEnabled(false);
         guestOption.setEnabled(false);
         messageText.setEnabled(false);
         messageText.grabFocus();
         statusColor.setBackground(Color.orange);
         break;
      }

      HostIP.setText(hostIP);
      Port.setText((new Integer(port)).toString());
      hostOption.setSelected(isHost);
      guestOption.setSelected(!isHost);
     statusField.setText(statusString);
      messages.append(toAppend.toString());
      toAppend.setLength(0);

      mainPanel.repaint();
   }

/**
 *Class for the Image button which is the extention of JButton
 **/
class ImageButton extends JButton {

  public ImageButton(String img) {
    this(new ImageIcon(img));
  }

  public ImageButton(ImageIcon icon) {
    setIcon(icon);
    setMargin(new Insets(0, 0, 0, 0));
    setIconTextGap(0);
    setBorderPainted(false);
    setBorder(null);
    setText(null);
    setSize(icon.getImage().getWidth(null), icon.getImage().getHeight(null));
  }
}

/**
 *Main method of the chat program
 *@exception Exception 
 *@exception InterruptedException on interruption
 *@param args Unused.
 **/
public static void main(String args[]) {
 	try {
	UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
	}
catch (Exception ex) {
}
      String s;
  Chat tw = new Chat();
  tw.setVisible(true);

      while (true) {
         try { // Poll every ~10 ms
            Thread.sleep(10);
         }
         catch (InterruptedException e) {}

         switch (connectionStatus) {
         case BEGIN_CONNECT:
            try {
               /**
                *Try to set up a server if host
                *If guest, try to connect to the server
                * If error, clean up and output an error message
                **/
               if (isHost) {
                  hostServer = new ServerSocket(port);
                  socket = hostServer.accept();
               }

              
               else {
                  socket = new Socket(hostIP, port);
               }

               in = new BufferedReader(new
                  InputStreamReader(socket.getInputStream()));
               out = new PrintWriter(socket.getOutputStream(), true);
               changeStatusTS(CONNECTED, true);
            }
            
            catch (IOException e) {
               cleanUp();
               changeStatusTS(DISCONNECTED, false);
            }
            break;
            
            

         case CONNECTED:
            try {
               // Send data
               if (toSend.length() != 0) {
                  out.print(toSend); out.flush();
                  toSend.setLength(0);
                  changeStatusTS(NULL, true);
               }

               /**
                *Receive data
                *Check if it is the end of a trasmission
                *Otherwise, receive what text
                *@see IOException
                */
               if (in.ready()) {
                  s = in.readLine();
                  if ((s != null) &&  (s.length() != 0)) {
                     
                     if (s.equals(END_CHAT_SESSION)) {
                        changeStatusTS(DISCONNECTING, true);
                     }

                     else {


                       try
    						{
    							String plainData=s,cipherText,decryptedText;
   								KeyGenerator keyGen = KeyGenerator.getInstance("AES");
    							keyGen.init(128);
    							SecretKey secretKey = keyGen.generateKey();
    							Cipher aesCipher = Cipher.getInstance("AES");
    							aesCipher.init(Cipher.ENCRYPT_MODE,secretKey);
    							byte[] byteDataToEncrypt = plainData.getBytes();
    							byte[] byteCipherText = aesCipher.doFinal(byteDataToEncrypt);
    							cipherText = new BASE64Encoder().encode(byteCipherText);
   								aesCipher.init(Cipher.DECRYPT_MODE,secretKey,aesCipher.getParameters());
    							byte[] byteDecryptedText = aesCipher.doFinal(byteCipherText);
    							decryptedText = new String(byteDecryptedText);
    					        appendToChatBox( strDate +" ]]------------->" +cipherText.toUpperCase() + "\n");
    						    Code.setText(decryptedText.toUpperCase()+ " \n");
    							changeStatusTS(NULL, true);
    }
    catch(Exception e)
    {

    }

                     }
                  }
               }
            }
            catch (IOException e) {
               cleanUp();
               changeStatusTS(DISCONNECTED, false);
            }
            break;
			/**
			 *Tell other chatter to disconnect as well
			 *Clean up (close all streams/sockets)
			 *do nothing
			 **/
         case DISCONNECTING:
            out.print(END_CHAT_SESSION); out.flush();

            cleanUp();
            changeStatusTS(DISCONNECTED, true);
            break;

         default: break; 
         }
      }
   }
}





// Action adapter for easy event-listener coding
class ActionAdapter implements ActionListener {
   public void actionPerformed(ActionEvent e) {}
}



